import importlib
import inspect
import logging
import os
import pkgutil
from abc import ABC
from pathlib import Path

from fastapi import FastAPI
from starlette.requests import Request

from env_config import settings

logger = logging.getLogger(__name__)


class BaseService:
    __abstract__ = True

    currentUser = None
    tableModel = None

    def __init__(self, request: Request):
        self.request = request
        self.conn = request.state.conn
        self.currentUser = self.request.state.current_user if hasattr(self.request.state, 'current_user') else None


def auto_register_services(app: FastAPI, *register_packages: str):
    def scan_directory(san_package: str, scan_package_path: Path):
        for _, module_name, ispkg in pkgutil.iter_modules([str(scan_package_path)]):
            full_module_name = f"{san_package}.{module_name}"
            if ispkg:
                logger.info(f"Found package: {full_module_name}")
                scan_directory(full_module_name, scan_package_path / module_name)
            else:
                logger.info(f"Found module: {full_module_name}")
                module = importlib.import_module(full_module_name)
                for attr_name in dir(module):
                    attr = getattr(module, attr_name)
                    if (
                            inspect.isclass(attr)  # 只考虑类
                            and issubclass(attr, BaseService)  # 必须是 BaseService 的子类
                            and hasattr(attr, 'instance')
                            and not inspect.isabstract(attr)  # 排除抽象类
                            and not attr_name.startswith("__")  # 排除私有属性
                            and not attr_name.endswith("__")  # 排除特殊属性
                            and not attr.__module__.startswith("builtins")  # 排除内置模块中的类
                            and attr.__module__ == full_module_name  # 只考虑当前模块中的类
                    ):
                        for base in attr.__bases__:
                            if issubclass(base, ABC):
                                logger.info(f"Registering {attr} as implementation of {base}")
                                app.dependency_overrides[base] = attr.instance

    for packages in register_packages:
        pkg_path = packages.replace('.', '/')
        package_path = Path(__file__).resolve().parent
        if not os.path.isabs(str(package_path)):
            package_path = Path(settings.root_path, pkg_path).resolve()
        logger.info(f"Scanning package: {packages} at {package_path}")
        scan_directory(packages, package_path)

